<template>
  <div
    class="draggable-box"
    :style="{ top: posY + 'px', left: posX + 'px' }"
    @dragover.prevent
    @drop.prevent="onDrop"
  >
    <div
      class="drag-handle"
      draggable="true"
      @dragstart="onDragStart"
      @dragend="onDragEnd"
    >
      <el-button size="small" type="primary" icon="el-icon-rank">
        拖拽按钮
      </el-button>
    </div>

    <div class="content">
      <slot />
    </div>

    <el-button
      size="small"
      type="danger"
      icon="el-icon-delete"
      @click="handleDelete"
      class="delete-btn"
      draggable="false"
    >
      删除
    </el-button>
  </div>
</template>

<script lang="ts" setup>
import { ref, defineEmits } from 'vue'

const emit = defineEmits(['delete'])

const posX = ref(100)
const posY = ref(100)

let startX = 0
let startY = 0
let dragging = false

const onDragStart = (event: DragEvent) => {
  dragging = true
  startX = event.clientX
  startY = event.clientY

  // 必须设置拖拽数据，否则拖拽无效
  event.dataTransfer?.setData('text/plain', 'dragging')

  // 设置空白拖拽图标，避免默认图标遮挡
  if (event.dataTransfer) {
    const img = new Image()
    img.src = ''
    event.dataTransfer.setDragImage(img, 0, 0)
  }
}

const onDragEnd = (event: DragEvent) => {
  if (!dragging) return
  dragging = false

  const deltaX = event.clientX - startX
  const deltaY = event.clientY - startY

  posX.value += deltaX
  posY.value += deltaY
}

const onDrop = (event: DragEvent) => {
  // 阻止默认行为，防止浏览器打开拖拽文件等
  event.preventDefault()
}

const handleDelete = () => {
  emit('delete')
}
</script>

<style scoped>
.draggable-box {
  position: absolute;
  width: 220px;
  min-height: 120px;
  background-color: #f5f7fa;
  border: 1px solid #dcdfe6;
  border-radius: 6px;
  padding: 10px;
  user-select: none;
  box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
}

.drag-handle {
  cursor: move;
  margin-bottom: 10px;
  display: inline-block;
}

.delete-btn {
  position: absolute;
  top: 6px;
  right: 6px;
}
</style>
